#include "../include/opencv100.h"

void opencv100::opencvq1(const Mat &img) 
{
    if (img.channels()!=3) {
        cout<<__func__<<","<<"img channels must be three"<<endl;
        return;
    }
    Mat res1=Mat::zeros(img.size(), img.type());
    cvtColor(img, res1, COLOR_BGR2RGB);
    
    namedWindow("res1", WINDOW_AUTOSIZE);
    imshow("res1", res1);

    Mat res2=Mat::zeros(img.size(), img.type());
    for (int i=0;i<img.rows;++i) {
        for (int j=0;j<img.cols;++j) {
            res2.at<Vec3b>(i, j)[0]=img.at<Vec3b>(i, j)[2];
            res2.at<Vec3b>(i, j)[1]=img.at<Vec3b>(i, j)[1];
            res2.at<Vec3b>(i, j)[2]=img.at<Vec3b>(i, j)[0];
        }
    }

    namedWindow("res2", WINDOW_AUTOSIZE);
    imshow("res2", res2);
}

void opencv100::opencvq2(const Mat &img)
{
    if (img.channels()==1) {
        cout<<__func__<<","<<"img is gray"<<endl;
        return;
    }
    else {
        Mat res1=Mat::zeros(img.size(), img.type());
        cvtColor(img, res1, COLOR_BGR2GRAY);

        namedWindow("res1", WINDOW_AUTOSIZE);
        imshow("res1", res1);

        Mat res2=Mat::zeros(img.size(), CV_8UC1);
        for (int i=0;i<img.rows;++i) {
            for (int j=0;j<img.cols;++j) {
                res2.at<uchar>(i, j)=img.at<Vec3b>(i, j)[2]*0.2126+
                img.at<Vec3b>(i, j)[1]*0.7152+img.at<Vec3b>(i, j)[0]*0.0722;
            }
        }

        namedWindow("res2", WINDOW_AUTOSIZE);
        imshow("res2", res2);
    }
}

void opencv100::opencvq3(const Mat &img, const int &th)
{
    Mat gray, res1;
    cvtColor(img, gray, COLOR_BGR2GRAY);
    threshold(gray, res1, th, 255, THRESH_BINARY);

    namedWindow("res1", WINDOW_AUTOSIZE);
    imshow("res1", res1);
    
    Mat res2=Mat::zeros(img.size(), gray.type());
    for (int i=0;i<gray.rows;++i) {
        for (int j=0;j<gray.cols;++j) {
            if (gray.at<uchar>(i, j)>th) {
                res2.at<uchar>(i, j)=255;
            }
            else {
                res2.at<uchar>(i, j)=0;
            }
        }
    }
    namedWindow("res2", WINDOW_AUTOSIZE);
    imshow("res2", res2);
}

void opencv100::opencvq4(const Mat &img)
{
    Mat gray, res1;
    cvtColor(img, gray, COLOR_BGR2GRAY);
    threshold(gray, res1, 0, 255, THRESH_OTSU);
    namedWindow("res1", WINDOW_AUTOSIZE);
    imshow("res1", res1);
    
    double maxvar=0, var=0;
    int th=0;

    for (int t=0;t<255;++t) {
        double w0=0, w1=0;
        double m0=0, m1=0;
        for (int i=0;i<gray.rows;++i) {
            for (int j=0;j<gray.cols;++j) {
                int val=gray.at<uchar>(i, j);
                if (val<t) {
                    w0++;
                    m0+=val;
                }
                else{
                    w1++;
                    m1+=val;
                }
            }
        }

        m0/=w0;
        m1/=w1;
        w0/=gray.rows*gray.cols;
        w1/=gray.rows*gray.cols;
        var=w1*w0*pow(m0-m1, 2);

        if (var>maxvar) {
            maxvar=var;
            th=t;
        }
    }

    Mat res2=Mat::zeros(img.size(), gray.type());
    for (int i=0;i<gray.rows;++i) {
        for (int j=0;j<gray.cols;++j) {
            if (gray.at<uchar>(i, j)>th) {
                res2.at<uchar>(i, j)=255;
            }
            else {
                res2.at<uchar>(i, j)=0;
            }
        }
    }

    namedWindow("res2", WINDOW_AUTOSIZE);
    imshow("res2", res2);
}

void opencv100::opencvq5(const Mat &img)
{
    Mat hsv, rgb;
    cvtColor(img, hsv, COLOR_BGR2HSV);
    namedWindow("res1", WINDOW_AUTOSIZE);
    imshow("res1", hsv);

    cvtColor(hsv, rgb, COLOR_HSV2BGR);
    namedWindow("res2", WINDOW_AUTOSIZE);
    imshow("res2", rgb);

    Mat hsv1=Mat::zeros(img.size(), CV_32FC3);
    
    for (int i=0;i<img.rows;++i) {
        for (int j=0;j<img.cols;++j) {
            double rt=static_cast<double>(img.at<Vec3b>(i,j)[2]);
            double gt=static_cast<double>(img.at<Vec3b>(i,j)[1]);
            double bt=static_cast<double>(img.at<Vec3b>(i,j)[0]);
            double cmax=fmax(rt, fmax(gt, bt));
            double cmin=fmin(rt, fmin(gt, bt));
            double delta=cmax-cmin;

            double h=0;
            if(fabs(delta)<0.001) {
                h=0;
            }
            else if (fabs(cmax-rt)<0.001) {
                h=fmod(((gt-bt)/delta), 6);
                h*=60;
            }
            else if (fabs(cmax-gt)<0.001) {
                h=((bt-rt)/delta)+2;
                h*=60;
            }
            else if (fabs(cmax-bt)<0.001) {
                h=((rt-gt)/delta)+4;
                h*=60;
            }
            
            if (h>359) {
                h-=360;
            }
            else if(h<0) {
                h+=360;
            }
            hsv1.at<Vec3f>(i,j)[0]=h*1/360;
            hsv1.at<Vec3f>(i,j)[1]=fabs(cmax)<0.001?0:(delta/cmax);
            hsv1.at<Vec3f>(i,j)[2]=cmax*1./255;
        }
    }

    namedWindow("hsv", WINDOW_AUTOSIZE);
    imshow("hsv", hsv1);
}